{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tiling imagery and labels using the `solaris` Python API\n",
    "\n",
    "This tutorial will walk you through an example case of using the `solaris` Python API to tile one of the SpaceNet cities - in this case, Rio de Janeiro. We'll assume that you have already [installed solaris](https://solaris.readthedocs.io/en/master/installation.html).\n",
    "\n",
    "__First__, downloaded and extracted two files from the `spacenet-dataset` AWS S3 bucket:\n",
    "\n",
    "1. Imagery: https://s3.amazonaws.com/spacenet-dataset/AOIs/AOI_1_Rio/PS-RGB/PS-RGB_mosaic_013022223133.tif\n",
    "2. Vector labels: https://spacenet-dataset.s3.amazonaws.com/AOIs/AOI_1_Rio/srcData/buildingLabels/Rio_Buildings_Public_AOI_v2.geojson\n",
    "\n",
    "Move both of these files to your working directory or alter the paths below to point to the files at the downloaded location.\n",
    "\n",
    "As you're getting started, your directory should have the following in it:\n",
    "\n",
    "- A directory named 3band which contains the imagery files\n",
    "- A directory named geojson which contains two files: Rio_Buildings_Public_AOI_v2.geojson and Rio_OUTLINE_Public_AOI.geojson (we only need the first of those two).\n",
    "\n",
    "Feel free to open up the imagery/vector labels in QGIS or another browser and explore to see what you're looking at."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Tiling the imagery\n",
    "\n",
    "For this working example we'll tile into 500-by-500-pixel chips beginning at the top left corner. Note that you can also tile based on the metric units covered by an image - for example, we could specify 250 meter-by-250 meter chips (which is the same size in this case). See the documentation for `sol.tile.raster_tile.RasterTiler()` for more details.\n",
    "\n",
    "Initialize the `RasterTiler` object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/miniconda3/envs/solaris/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:526: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint8 = np.dtype([(\"qint8\", np.int8, 1)])\n",
      "/opt/miniconda3/envs/solaris/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:527: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint8 = np.dtype([(\"quint8\", np.uint8, 1)])\n",
      "/opt/miniconda3/envs/solaris/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:528: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint16 = np.dtype([(\"qint16\", np.int16, 1)])\n",
      "/opt/miniconda3/envs/solaris/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:529: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_quint16 = np.dtype([(\"quint16\", np.uint16, 1)])\n",
      "/opt/miniconda3/envs/solaris/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:530: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  _np_qint32 = np.dtype([(\"qint32\", np.int32, 1)])\n",
      "/opt/miniconda3/envs/solaris/lib/python3.6/site-packages/tensorflow/python/framework/dtypes.py:535: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.\n",
      "  np_resource = np.dtype([(\"resource\", np.ubyte, 1)])\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initializing Tiler...\n",
      "Tiler initialized.\n",
      "dest_dir: rio_chips\n",
      "dest_crs will be inferred from source data.\n",
      "src_tile_size: (500, 500)\n",
      "tile size units metric: False\n"
     ]
    }
   ],
   "source": [
    "import solaris as sol\n",
    "import os\n",
    "\n",
    "raster_tiler = sol.tile.raster_tile.RasterTiler(dest_dir='rio_chips',  # the directory to save images to\n",
    "                                                src_tile_size=(500, 500),  # the size of the output chips\n",
    "                                                verbose=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This object can be re-used with the same parameters for multiple images if desired. This way, you can tile multiple images collected over the same geography with the same settings. There are additional arguments that you can provide (for example, the destination coordinate reference system).\n",
    "\n",
    "To tile the imagery, pass the image file to the tiler's `tile()` method, which returns the CRS of the source raster for vector tiling:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "0it [00:00, ?it/s]The following warnings were found:\n",
      "- The file is greater than 512xH or 512xW, it is recommended to include internal overviews\n",
      "\n",
      "The following errors were found:\n",
      "- The offset of the main IFD should be 8 for ClassicTIFF or 16 for BigTIFF. It is 93844024 instead\n",
      "- The offset of the first block of the image should be after its IFD\n",
      "3it [00:00, 23.16it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Beginning tiling...\n",
      "Checking input data...\n",
      "COG: False\n",
      "[1, 2, 3]\n",
      "Source CRS: EPSG:4326\n",
      "Destination CRS: EPSG:4326\n",
      "Inputs OK.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "1600it [01:04, 24.86it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tiling complete. Cleaning up...\n",
      "Done.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "raster_bounds_crs = raster_tiler.tile('/Users/nweir/code/cosmiq_repos/solaris/PS-RGB_mosaic_013022223133.tif')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This should throw a few warnings/errors about the input file, which you can ignore. You'll create 1600 files in your \"rio_chips\" subdirectory, one for each 500x500 tile. The filenames are in the format `[src-filename]\\_[longitude]\\_[latitude].tif`. Reprojection takes a while, so be patient.\n",
    "\n",
    "Once that process finishes, we'll use these auto-generated tile boundaries, which are stored in `raster_tiler`, to create vector tiles."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These bounds are in the format `[left, bottom, right, top]` in the input file CRS. The following line prints the first set of bounds (there are 1600 in the list):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(-43.681640625, -22.939453125, -43.67939668543198, -22.937209185431986)\n"
     ]
    }
   ],
   "source": [
    "print(raster_tiler.tile_bounds[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`raster_tiler.tile_bounds` is passed as an argument into the `VectorTiler` instance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "0it [00:00, ?it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Preparing the tiler...\n",
      "Initialization done.\n",
      "Num tiles: 1600\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "1600it [02:16, 11.74it/s]\n"
     ]
    }
   ],
   "source": [
    "vector_tiler = sol.tile.vector_tile.VectorTiler(dest_dir='rio_labels',\n",
    "                                                verbose=True)\n",
    "vector_tiler.tile('/Users/nweir/code/cosmiq_repos/solaris/Rio_Buildings_Public_AOI_v2.geojson',\n",
    "                  tile_bounds=raster_tiler.tile_bounds,\n",
    "                  tile_bounds_crs=raster_bounds_crs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "...And you're done! Simple as that. For more details, check out the [tiling API docs](https://solaris.readthedocs.io/en/master/api.html)."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "solaris",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
